package com.atguigu.test.config;

import com.atguigu.test.mvc.editor.MyMessageConverter;
import com.atguigu.test.mvc.my.MyBeanNameUrlHandlerMapping;
import com.atguigu.test.mvc.my.MyRequestMappingHandlerAdapter;
import com.atguigu.test.mvc.my.MySimpleControllerHandlerAdapter;
import com.atguigu.test.mvc.my.MyTokenHandlerMethodArgumentResolver;
import com.atguigu.test.mvc.view.MyView;
import com.atguigu.test.po.LifeCycleBean;
import com.atguigu.test.processor.MyLifeCycleBeanPostProcessor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistrarBeanPostProcessor;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.cache.concurrent.ConcurrentMapCache;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.RouterFunctions;
import org.springframework.web.servlet.function.ServerResponse;
import org.springframework.web.servlet.function.support.HandlerFunctionAdapter;
import org.springframework.web.servlet.function.support.RouterFunctionMapping;
import org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.servlet.resource.CachingResourceResolver;
import org.springframework.web.servlet.resource.EncodedResourceResolver;
import org.springframework.web.servlet.resource.PathResourceResolver;
import org.springframework.web.servlet.resource.ResourceHttpRequestHandler;
import org.springframework.web.servlet.view.BeanNameViewResolver;

import java.util.*;

import static org.springframework.web.servlet.function.RequestPredicates.GET;

/**
 * @author zp
 * @version 1.0
 * @description: springWeb 配置类
 * 排除Configuration和ControllerAdvice注解的类 防止冲突
 * ControllerAdvice不排除 容易提取处理异常 无效果
 * @date 2022/12/14 19:39
 */
@Slf4j
@Configuration
@ComponentScan(value = "com.atguigu.test.mvc",
        excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION
                , classes = {Configuration.class}), @ComponentScan.Filter(type = FilterType.ANNOTATION
                , classes = {ControllerAdvice.class})})
public class SpringWebBeanNameConfig {
    /**
     * @return ServletWebServerFactory
     * @description: 配置web容器的环境 这里设置tomcat的web环境
     * @author zp
     * @date: 2022/12/14 19:49
     */
    @Bean
    public ServletWebServerFactory servletWebServerFactory() {
        return new TomcatServletWebServerFactory();
    }

    /**
     * @return DispatcherServlet
     * @description: 注入一个默认的servlet控制器 也是程序访问的入口
     * @author zp
     * @date: 2022/12/14 19:49
     */
    @Bean
    public DispatcherServlet dispatcherServlet() {
        return new DispatcherServlet();
    }

    /**
     * @param dispatcherServlet
     * @return DispatcherServletRegistrationBean
     * @description: 控制器和路径的绑定类 绑定一个路径
     * @author zp
     * @date: 2022/12/14 19:50
     */
    @Bean
    public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet) {
        return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
    }
    /**
     * @description: 简单的url映射器
     * @author zp
     * @date: 2023/1/29 18:48
     * @param applicationContext
     * @return SimpleUrlHandlerMapping
     */
    @Bean
    public SimpleUrlHandlerMapping simpleUrlHandlerMapping(ApplicationContext applicationContext){
        SimpleUrlHandlerMapping simpleUrlHandlerMapping = new SimpleUrlHandlerMapping();
        Map<String, ResourceHttpRequestHandler> map = applicationContext.getBeansOfType(ResourceHttpRequestHandler.class);
        simpleUrlHandlerMapping.setUrlMap(map);
        System.out.println("获取的连接映射"+map);
        return simpleUrlHandlerMapping;
    }
    /**
     * @description:  配置简单的http请求适配器
     * @author zp
     * @date: 2023/1/29 18:48
     * @return HttpRequestHandlerAdapter
     */
    @Bean
    public HttpRequestHandlerAdapter httpRequestHandlerAdapter(){
        return new HttpRequestHandlerAdapter();
    }
    /**
     * @description: 配置资源响应
     * @author zp
     * @date: 2023/1/29 18:50
     * @return ResourceHttpRequestHandler
     */
    @Bean("/**")
    public ResourceHttpRequestHandler resourceHttpRequestHandler(){
        ResourceHttpRequestHandler resourceHttpRequestHandler = new ResourceHttpRequestHandler();
        // 配置静态资源的映射路径
        resourceHttpRequestHandler.setLocations(Collections.singletonList(new ClassPathResource("templates/")));
        // 设置静态资源解析器
        resourceHttpRequestHandler.setResourceResolvers(Arrays.asList(
                // 缓存资源解析器
                new CachingResourceResolver(new ConcurrentMapCache("cache1")),
                // 压缩资源解析器 对应gzip压缩
                new EncodedResourceResolver(),
                // 资源路径解析器
                new PathResourceResolver()
        ));

        return resourceHttpRequestHandler;
    }
    /**
     * @description:  配置图片资源映射
     * @author zp
     * @date: 2023/1/29 19:03
     * @return ResourceHttpRequestHandler
     */
    @Bean("/img/**")
    public ResourceHttpRequestHandler resourceHttpRequestHandler1(){
        ResourceHttpRequestHandler resourceHttpRequestHandler = new ResourceHttpRequestHandler();
        // 配置静态资源的映射路径
        resourceHttpRequestHandler.setLocations(Collections.singletonList(new ClassPathResource("templates/img/")));
        return resourceHttpRequestHandler;
    }

//    /**
//     * @description:  使用bean的名称映射的方式的映射器
//     * @author zp
//     * @date: 2023/1/27 15:49
//     * @return BeanNameUrlHandlerMapping
//     */
//    @Bean
//    public BeanNameUrlHandlerMapping beanNameUrlHandlerMapping(){
//        return new BeanNameUrlHandlerMapping();
//    }
    /**
     * @description: 自定义的beanName映射器
     * @author zp
     * @date: 2023/1/27 16:21
     * @return MyBeanNameUrlHandlerMapping
     */
//    @Bean
//    public MyBeanNameUrlHandlerMapping myBeanNameUrlHandlerMapping(){
//        return new MyBeanNameUrlHandlerMapping();
//    }
    /**
     * @description: 自定义简单的映射适配器
     * @author zp
     * @date: 2023/1/27 16:21
     * @return MySimpleControllerHandlerAdapter
     */
//    @Bean
//    public MySimpleControllerHandlerAdapter mySimpleControllerHandlerAdapter(){
//        return new MySimpleControllerHandlerAdapter();
//    }

    /**
     * @return RouterFunctionMapping
     * @description: 定义函数式方式映射请求
     * @author zp
     * @date: 2023/1/28 20:00
     */
//    @Bean
//    public RouterFunctionMapping routerFunctionMapping() {
//        return new RouterFunctionMapping();
//    }

    /**
     * @return HandlerFunctionAdapter
     * @description: 函数式映射适配器
     * @author zp
     * @date: 2023/1/28 20:02
     */
//    @Bean
//    public HandlerFunctionAdapter handlerFunctionAdapter() {
//        return new HandlerFunctionAdapter();
//    }

    /**
     * @return RouterFunction<ServerResponse>
     * @description: 设置函数式请求
     * @author zp
     * @date: 2023/1/28 20:06
     */
//    @Bean
//    public RouterFunction<ServerResponse> getModelBuildingRouters() {
//        return RouterFunctions.route(GET("/router"),
//                request -> ServerResponse.ok().body("hello router")
//        );
//    }


//    /**
//     * @description:  使用简单的映射适配器
//     * @author zp
//     * @date: 2023/1/27 15:49
//     * @return SimpleControllerHandlerAdapter
//     */
//    @Bean
//    public SimpleControllerHandlerAdapter simpleControllerHandlerAdapter(){
//        return new SimpleControllerHandlerAdapter();
//    }
    }
